#include "EventLoop.h"
#include "Log.h"
struct EventLoop *CreateEventInit()
{
    return CreateEventInitEx(NULL);
}

// 创建子线程
struct EventLoop *CreateEventInitEx(const char *threadName)
{

    struct EventLoop *evloop = (struct EventLoop *)malloc(sizeof(struct EventLoop));
    if (!evloop)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    evloop->isQuit = false;            // 记录是否退出
    evloop->threadId = pthread_self(); // 获取当前线程ID

    // if(threadName==NULL)
    // {
    //     evloop->threadName = "MainThread"; //线程名称
    // }else{
    //     evloop->threadName = threadName; //线程名称
    // }
    // c语言字符串拷贝

    strcpy(evloop->threadName, threadName == NULL ? "main thread" : threadName); // 线程名称

    // evloop->threadName = threadName;                                       // 线程名称
    pthread_mutex_init(&evloop->mutex, NULL); // 初始化互斥锁 第一个参数是初始化饿互斥锁 第二个参数是互斥锁得属性
    // 这句代码好好理解
    evloop->dispatcher = &SelectDispatcher; // 事件分发器
    // 这样绑定了之后是用的epollDispather里面的epollinit函数 ,dispatcher 是对函数指针赋值了的

    evloop->DispatcherData = evloop->dispatcher->init();
    if (!evloop->DispatcherData)
    {
        free(evloop);
        perror("dispatcher init");
        exit(EXIT_FAILURE);
    }
    // 链表初始化
    evloop->head = NULL;
    evloop->tail = NULL;
    // -------------------------------------------------------------------------

    evloop->channelMap = channelmapInit(128);
    if (!evloop->channelMap)
    {
        free(evloop->DispatcherData);
        free(evloop);
        perror("channelmap init");
        exit(EXIT_FAILURE);
    }

    // 创建局部通信的两个fd
    // 这是的fd  4 5 socketpair

    int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, evloop->sockfdPair);

    if (ret == -1)
    {
        perror("socketpair");
        free(evloop->channelMap);
        free(evloop->DispatcherData);
        free(evloop);
        exit(EXIT_FAILURE);
    }

    // 指定sockfdPair[0]发送数据 指定sockfdPair[1]接收数据
    // Debug("CreateEventInitEx");
    struct Channel *channel = ChannelInit(evloop->sockfdPair[1], ReadEvent, readLocalMessage, NULL, NULL, evloop);
    if (!channel)
    {
        close(evloop->sockfdPair[0]);
        close(evloop->sockfdPair[1]);
        free(evloop->channelMap);
        free(evloop->DispatcherData);
        free(evloop);
        perror("Channel init");
        exit(EXIT_FAILURE);
    }
    // 把channel添加到任务队列中
    // Debug("CreateEventInitEx");
    eventAddTask(evloop, channel, ADD);

    return evloop;
}

int eventLoopRun(struct EventLoop *evloop)
{
    // Debug("start eventLoopRun");
    assert(evloop != NULL);
    // int timeout =1;
    // 取出事件分发和检测模型
    struct Dispatcher *dispatcher = evloop->dispatcher;
    // 比较线程ID是否正常
    if (evloop->threadId != pthread_self())
    {
        return -1;
    }
    // 事件分发和检测模型

    while (!evloop->isQuit)
    {
        // Debug("这一行我来了");
        // 事件分发
        int timeout = 2;
        // 首先你要明白这个dispatch是干了什么 处理fd 对应的事件
        dispatcher->dispatch(evloop, timeout); // 超时时长

        // Debug("这一行我来了");
        // 这个函数是把fd的事件修改
        eventLoopProcess(evloop);
    }
    return 0;
}

int eventActivate(struct EventLoop *evloop, int fd, int events)
{

    if (fd < 0 || evloop == NULL)
    {
        return -1;
    }
    // 想的不够充分？需要枷锁 ，然后处理完一个节点删除一个节点
    struct Channel *channel = evloop->channelMap->list[fd];
    assert(channel->fd == fd);

    if (events & ReadEvent && channel->readCallBack)
    {
        // 其实是再这里绑定的
        channel->readCallBack(channel->arg);
    }

    if (events & WriteEvent && channel->writeCallBack)
    {
        // 其实是再这里绑定的
        channel->writeCallBack(channel->arg);
    }

    return 0;
}

int eventAddTask(struct EventLoop *evloop, struct Channel *channel, int type)
{
    pthread_mutex_lock(&evloop->mutex);

    // 创建节点 添加到任务队列中
    struct ChannelElement *node = (struct ChannelElement *)malloc(sizeof(struct ChannelElement));
    node->channel = channel;
    node->type = type;
    node->next = NULL;

    // 链表为空和不为空两种情况
    if (evloop->head == NULL)
    {
        evloop->head = node;
        evloop->tail = node;
    }
    else
    {
        evloop->tail->next = node; // 添加
        evloop->tail = node;       // 后移
    }
    pthread_mutex_unlock(&evloop->mutex);

    // 处理节点
    // 细节
    // 对于链表节点得添加：可能是当前线程 也有可能是主线程
    // 修改fd事件，当先线程发起，当前线程处理
    // 添加新的fd，添加任务得节点是由主线程发起得

    // 2 对线程进行判断，不能让主线程处理任务队列，需要有当前得子线程处理

    // 理解为什么当前线程也有添加操作 。我想对这个文件描述符从读变为 读写

    // 理解了 为什么会这样 ，因为主线程经过accpet 可能会把添加任务 ，所以说这里就用两种角色 ，但是呢？evloop->threadId一定是子线程的 ，因为这是在创建的时候决定的，
    // 但是运行进来的线程可能有两种，一个是子线程，一个是主线程
    // 这里假设了一个场景，当前饿eventloop是子线程的
    if (evloop->threadId == pthread_self())
    {
        // 子线程 ，就直接处理这个，把文件秒描述符添加到模型中
        eventLoopProcess(evloop);
    }
    else
    {
        // 主线程 -> 告诉子线程可以处理任务了
        // 1 正在处理任务
        // 2 被阻塞了 select poll epoll
        // 额外追加一个特殊的文件描述符 -》用来唤醒select poll epoll
        taskWakeUp(evloop);
    }
    return 0;
}

// 写数据
void taskWakeUp(struct EventLoop *evloop)
{
    const char *msg = "我是要成为海贼王的男人！！！";
    write(evloop->sockfdPair[0], msg, strlen(msg));
}

// 读数据
int readLocalMessage(void *arg)
{
    struct EventLoop *evloop = (struct EventLoop *)arg;
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));
    read(evloop->sockfdPair[1], buffer, sizeof(buffer));
    return 0;
}

// 处理任务队列
int eventLoopProcess(struct EventLoop *evloop)
{
    // Debug("eventLoopProcess");
    pthread_mutex_lock(&evloop->mutex);
    struct ChannelElement *head = evloop->head;

    // if (head == NULL)
    // {
    //     // 这里注意，注意注意
    //     pthread_mutex_unlock(&evloop->mutex);
    //     return 0;
    // }
    // struct ChannelElement *next = NULL;
    while (head != NULL)
    {
        // struct ChannelElement *node = evloop->head;
        struct Channel *channel = head->channel;

        // 如果next有值 ，我就让next移动
        // 我得到一个节点，然后处理这个节点
        // 想通了其实就是再根据type对fd进行修改
        if (head->type == ADD)
        {
            eventLoopAdd(evloop, channel);
        }
        else if (head->type == DELETE)
        {
            eventLoopDelete(evloop, channel);
        }
        else if (head->type == MODIFY)
        {
            eventLoopModify(evloop, channel);
        }
        struct ChannelElement *tmp = head;
        head = head->next;
        free(tmp);
    }
    // 处理完之后链表初始化
    evloop->head = NULL;
    evloop->tail = NULL;
    pthread_mutex_unlock(&evloop->mutex);
    // Debug("end eventLoopProcess");
    return 0;
}

// 处理每个节点的任务
int eventLoopAdd(struct EventLoop *evloop, struct Channel *channel)
{
    // Debug("eventLoopAdd start");
    // 1 要建立联系 fd 和 channelMap
    int fd = channel->fd;
    struct ChannelMap *channelMap = evloop->channelMap;
    // 2 判断fd是否已经存在，如果存在，则修改

    if (fd >= channelMap->size)
    {
        // 扩容bool makeMapRoom(struct ChannelMap* map,int newSize, int unitSize);
        if (!makeMapRoom(channelMap, fd, sizeof(struct Channel *)))
        {
            return -1;
        }
    }
    // 统一判断存在否
    if (channelMap->list[fd] == NULL)
    {
        // 证明为空，直接添加
        // 写一个对应关系 ，fd - >channel*
        channelMap->list[fd] = channel;
        int ret = evloop->dispatcher->add(channel, evloop);
        if (ret == -1)
        {
            channelMap->list[fd] = NULL;
            return -1;
        }
    }
    // Debug("eventLoopAdd end");
    return 0;
}
int eventLoopDelete(struct EventLoop *evloop, struct Channel *channel)
{
    int fd = channel->fd;
    struct ChannelMap *channelMap = evloop->channelMap;

    if (fd >= channelMap->size)
    {
        return -1;
    }
    // 本身就没有这个事件
    // 这里写的不一样，
    int ret;
    if (channelMap->list[fd] == NULL)
    {
        return 0;
    }
    ret = evloop->dispatcher->remove(channel, evloop); // 这个是从io多路复用中删除
    evloop->channelMap->list[fd] = NULL;               // 这个是在对应map中删除

    return ret;
}
int eventLoopModify(struct EventLoop *evloop, struct Channel *channel)
{

    int fd = channel->fd;
    struct ChannelMap *channelMap = evloop->channelMap;

    // 如果都没有保存过，不存在修改
    if (fd >= channelMap->size || channelMap->list[fd] == NULL)
    {
        return -1;
    }

    int ret = evloop->dispatcher->modify(channel, evloop);
    return ret;
}

int destoryChannel(struct EventLoop *evloop, struct Channel *channel)
{
    int fd = channel->fd;
    struct ChannelMap *channelMap = evloop->channelMap;
    channelMap->list[fd] = NULL;
    close(fd);
    // 删除对应关系
    free(channel);
    return 0;
}